﻿namespace BM.Tools.WebControls.MForm.Controls.ValueHandlers
{
    using System;
    using System.ComponentModel;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    using BM.Tools.WebControls.MForm.Controls.Items;
    using BM.Tools.WebControls.MForm.ScriptReferences;

    using Generator;

    /// <summary>
    /// The control value handler binds the <see cref="LeafItem" /> control with a single control that is inside the value handler
    /// </summary>
    /// <typeparam name="T">
    /// the type of the control 
    /// </typeparam>
    public abstract class ControlValueHandler<T> : ValueHandler where T : Control, new()
    {
        private string viewModeControlValue;

        private T control = new T();                            

        private Label viewModeControl = new Label();

        /// <summary>
        /// Gets the contol's type name.
        /// </summary>
        /// <value>
        /// The type name.
        /// </value>
        public virtual string TypeName
        {
            get
            {
                return GetType().Name;
            }
        }

        /// <summary>
        /// Gets or sets the value that should appear in the view mode control
        /// </summary>
        public string ViewModeControlValue
        {
            get
            {
                return viewModeControlValue ?? DefaultViewModeControlValue;
            }

            set
            {
                viewModeControlValue = value;
            }
        }

        /// <summary>
        /// Gets or sets Control.
        /// </summary>
        /// <value>
        /// The control.
        /// </value>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        protected virtual T Control
        {
            get
            {
                return control;
            }

            set
            {
                control = value;
            }
        }

        /// <summary>
        /// Gets the value that should appear in the view mode control.
        /// </summary>        
        protected string FormattedViewModeControlValue
        {
            get
            {
                var value = ViewModeControlValue;
                foreach (var valueFormatter in Owner.Basis.ValueFormatters)
                {
                    value = valueFormatter.Format(value);
                }

                return value;
            }
        }

        /// <summary>
        /// Gets a web control displayed in case of a view mode.
        /// </summary>
        protected virtual Label ViewModeControl
        {
            get
            {                
                return viewModeControl;
            }
        }

        /// <summary>
        /// Gets the default value that is by default displayed in the view mode control.
        /// </summary>
        protected virtual string DefaultViewModeControlValue
        {
            get
            {
                return Value;
            }
        }

        /// <summary>
        /// Adds the control and the hidden input to the leaf item
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            OnChildControlCreating();
            Controls.Add(ViewModeControl);
            Controls.Add(Control);
        }

        /// <summary>
        /// Register control state requirement
        /// </summary>
        /// <param name="e">
        /// The event args.
        /// </param>
        protected override void OnInit(EventArgs e)
        {
            Page.RegisterRequiresControlState(this);
            if (!Owner.Basis.IsDuringGeneration && String.IsNullOrEmpty(Control.ID))
            {
                Control.ID = "Ctrl";
            } 

            base.OnInit(e);
        }

        /// <summary>
        /// loads value kept in control state if in view mode
        /// </summary>
        /// <param name="savedState">
        /// The saved state.
        /// </param>
        protected override void LoadControlState(object savedState)
        {
            var stateText = savedState as string;
            if (stateText != null)
            {
                Value = stateText;
            }
        }

        /// <summary>
        /// always saves the value of the value handler
        /// </summary>
        /// <returns>
        /// the control state value
        /// </returns>
        protected override object SaveControlState()
        {
            return Value;
        }

        /// <summary>
        /// Includes the associated scripts
        /// </summary>
        protected virtual void IncludeScripts()
        {
            ScriptIncluder.IncludeResources(this);
        }

        /// <summary>
        /// This virtual method may be invoked when the child control is created
        /// </summary>
        protected virtual void OnChildControlCreating()
        {
        }

        /// <summary>
        /// Prepares the control and the hidden input and includes scripts
        /// </summary>
        /// <param name="e">
        /// The event args.
        /// </param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            Owner.Attributes["type"] = TypeName;
            IncludeScripts();
            PrepareControl();
            PrepareViewModeControl();
            HideControlAccordingToMode();
        }

        /// <summary>
        /// Prepares the view mode control
        /// </summary>
        protected virtual void PrepareViewModeControl()
        {
            ViewModeControl.Text = FormattedViewModeControlValue;            
            ViewModeControl.Attributes["value"] = Value;           
        }

        /// <summary>
        /// Prepares the control
        /// </summary>
        protected virtual void PrepareControl()
        {
            if (String.IsNullOrEmpty(Value))
            {
                Value = Owner.DefaultValue;
            }                    
        }    

        /// <summary>
        /// Renders the control        
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        protected override void Render(HtmlTextWriter writer)
        {
            if (DesignMode)
            {
                PrepareControl();
            }
            
            base.Render(writer);
        }

        private void HideControlAccordingToMode()
        {
            Control.Visible = Owner.Mode == FormBuilderMode.Edit;
            ViewModeControl.Visible = Owner.Mode == FormBuilderMode.View;            
        }
    }
}